<template>
  <el-card class="box-card">
    <el-form ref="form" :model="spu" :rules="rules" label-width="80px">
      <el-form-item label="SPU名称" prop="spuName">
        <el-input v-model="spu.spuName" placeholder="请输入SPU名称" />
      </el-form-item>
      <el-form-item label="SPU品牌" prop="tmId">
        <el-select v-model="spu.tmId" placeholder="请选择SPU品牌">
          <el-option
            v-for="tm in trademarkList"
            :key="tm.id"
            :label="tm.tmName"
            :value="tm.id"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="SPU描述" prop="description">
        <el-input
          v-model="spu.description"
          type="textarea"
          placeholder="请输入SPU名称"
        />
      </el-form-item>
      <el-form-item label="SPU图片" prop="spuImageList">
        <!--
          accept 允许上传的文件类型
          action 上传文件的地址
          on-preview 预览图片
          on-remove 删除图片
          on-success 上传图片成功
          before-upload 上传图片之前
          limit 限制图片上传最大数量
          class 通过类名来决定上传按钮的显示隐藏
         -->
        <el-upload
          :limit="limit"
          accept="image/jpeg,image/jpg,image/png"
          :class="{ 'save-spu-upload': spu.spuImageList.length === limit }"
          :action="`${baseURL}/admin/product/fileUpload`"
          list-type="picture-card"
          :file-list="formatSpuImageList"
          :on-preview="handlePictureCardPreview"
          :on-remove="handleRemove"
          :on-success="handleAvatarSuccess"
          :before-upload="beforeAvatarUpload"
        >
          <i class="el-icon-plus"></i>
          <div slot="tip" class="el-upload__tip">
            只能上传jpg/png文件，且不超过1M
          </div>
        </el-upload>
        <el-dialog :visible.sync="dialogVisible" width="450px">
          <img width="100%" :src="dialogImageUrl" alt="" />
        </el-dialog>
      </el-form-item>
      <el-form-item label="销售属性" prop="spuSaleAttrList">
        <el-select
          v-model="spu.saleAttrName"
          :placeholder="`还剩${filterBaseSaleAttrList.length}个销售属性`"
        >
          <el-option
            v-for="baseSaleAttr in filterBaseSaleAttrList"
            :key="baseSaleAttr.id"
            :label="baseSaleAttr.name"
            :value="baseSaleAttr.name"
          />
        </el-select>
        <el-button
          :disabled="!spu.saleAttrName"
          type="primary"
          icon="el-icon-plus"
          style="margin-left: 15px"
          @click="addSpuAttr"
          >添加销售属性值</el-button
        >
        <el-table :data="spu.spuSaleAttrList" border class="table">
          <el-table-column
            type="index"
            label="序号"
            width="50"
            align="center"
          />
          <el-table-column prop="saleAttrName" label="属性名" width="90" />
          <el-table-column label="属性值列表">
            <template v-slot="{ row, $index }">
              <el-tag
                v-for="(tag, index) in row.spuSaleAttrValueList"
                :key="index"
                closable
                disable-transitions
                size="small"
                class="tag-attr-value"
                @close="handleClose(tag, row)"
              >
                {{ tag.saleAttrValueName }}
              </el-tag>
              <el-button
                v-if="row.isShowEdit"
                icon="el-icon-plus"
                size="mini"
                @click="addsaleAttrName(row, $index)"
                >添加属性名</el-button
              >
              <el-input
                v-else
                size="mini"
                style="width: 150px"
                placeholder="请输入属性值"
                :ref="$index"
                v-model="spu.saleAttrValueName"
                @blur="addSaleAttrValue(row)"
              />
            </template>
          </el-table-column>
          <el-table-column label="操作" width="90">
            <template v-slot="{ row, $index }">
              <el-button
                type="danger"
                icon="el-icon-delete"
                size="mini"
                @click="spu.spuSaleAttrList.splice($index, 1)"
              />
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm"> 确定 </el-button>
        <el-button @click="$emit('isShowSpu', 1)"> 取消 </el-button>
      </el-form-item>
    </el-form>
  </el-card>
</template>

<script>
import { reqGetAllTrademarkList } from '@/api/product/trademark'
import {
  reqGetBaseSaleAttrList,
  reqSaveSpuInfo,
  reqUpdateSpu,
  reqGetSpuImageList,
  reqGetSpuSaleAttrList
} from '@/api/product/spu'
import { mapState } from 'vuex'
export default {
  name: 'SaveSpu',
  props: {
    currentSpu: Object
  },
  data() {
    function validator(rule, value, callback) {
      // value -> spuSaleAttrList 销售属性列表
      if (!value.length) {
        callback('至少添加一个销售属性')
        return
      }

      // 每个销售属性至少添加一个销售属性值
      if (
        !value.every((saleAttr) => saleAttr.spuSaleAttrValueList.length > 0)
      ) {
        callback('每个销售属性至少添加一个销售属性值')
        return
      }
      // 必须调用
      callback()
    }
    return {
      dialogImageUrl: '',
      dialogVisible: false,
      trademarkList: [],
      baseSaleAttrList: [],
      filterBaseSaleAttrList: [],
      spu: {
        // spu名称
        spuName: '',
        // 品牌
        tmId: '',
        // 描述
        description: '',
        // 图片列表
        spuImageList: [],
        // 销售属性列表
        spuSaleAttrList: [],
        // 销售属性名
        saleAttrName: '',
        // 销售属性值
        saleAttrValueName: '',
        ...this.currentSpu
      },
      rules: {
        // spu名称
        spuName: [
          { required: true, message: '请输入spu名称', trigger: 'blur' }
        ],
        // 品牌
        tmId: [{ required: true, message: '请选择spu品牌' }],
        // 描述
        description: [
          { required: true, message: '请输入spu描述', trigger: 'blur' }
        ],
        // 图片列表
        spuImageList: [{ required: true, message: '请上传spu图片' }],
        // 销售属性列表
        spuSaleAttrList: [{ required: true, validator }]
      },
      baseURL: process.env.VUE_APP_BASE_API,
      // 图片上传的最大数量
      limit: 4
    }
  },
  async mounted() {
    try {
      const { id } = this.spu
      let promises = [reqGetAllTrademarkList(), reqGetBaseSaleAttrList()]
      // 有id就是更新spu
      // 需要额外发送两个请求，请求数据
      if (id) {
        promises = promises.concat([
          reqGetSpuImageList(id),
          reqGetSpuSaleAttrList(id)
        ])
      }
      const [
        trademarkListResponse,
        baseSaleAttrListResponse,
        spuImageListResponse,
        spuSaleAttrListResponse
      ] = await Promise.all(promises)

      this.trademarkList = trademarkListResponse.data
      this.baseSaleAttrList = baseSaleAttrListResponse.data
      this.filterBaseSaleAttrList = baseSaleAttrListResponse.data

      // 判断有无（因为添加SPU是没有的）
      if (spuImageListResponse) {
        this.spu.spuImageList = spuImageListResponse.data
        this.spu.spuSaleAttrList = spuSaleAttrListResponse.data.map((row) => ({
          ...row,
          isShowEdit: true
        }))
      }
    } catch (e) {
      this.$message({
        type: 'error',
        message: '获取数据失败'
      })
    }
  },
  computed: {
    ...mapState('category', ['category3Id']),
    // filterBaseSaleAttrList() {
    //   return this.baseSaleAttrList.filter(baseSaleAttr => {
    //     // 在表格中的销售属性列表中，找是否存在基础销售属性的值
    //     // 如果存在，说明这个基础销售属性的值被添加到表格中的销售属性列表中
    //     // 将添加进去的过滤掉
    //     return !this.spu.spuSaleAttrList.find(
    //       saleAttr => saleAttr.saleAttrName === baseSaleAttr.name
    //     )
    //   })
    // }
    formatSpuImageList() {
      return this.spu.spuImageList.map((img) => {
        return {
          name: img.imgName,
          url: img.imgUrl,
          // 添加uid，为了让上传图片时不会抖动
          // 保证uid前后值一样
          // img.uid 刚刚上传的图片才有
          // img.id 已经上传好的图片才有
          uid: img.uid || img.id
        }
      })
    }
  },
  watch: {
    'spu.spuSaleAttrList': {
      // immediate: true,
      deep: true,
      handler(newList) {
        this.filterBaseSaleAttrList = this.baseSaleAttrList.filter(
          (baseSale) => {
            return !newList.find(
              (saleAttr) => saleAttr.saleAttrName === baseSale.name
            )
          }
        )
      }
    }
  },
  methods: {
    // 提交表单事件回调
    submitForm() {
      this.$refs.form.validate(async(valid) => {
        if (valid) {
          const {
            spuName,
            tmId,
            description,
            spuImageList,
            spuSaleAttrList,
            id
          } = this.spu
          const { category3Id } = this
          const options = {
            spuName,
            tmId,
            description,
            spuImageList,
            spuSaleAttrList,
            category3Id
          }
          if (id) {
            // 有id就发送更新请求
            await reqUpdateSpu({ ...options, id })
          } else {
            // 添加请求
            await reqSaveSpuInfo(options)
          }
          this.$message({
            type: 'success',
            message: `${id ? '修改' : '添加'}spu成功`
          })
          this.$emit('isShowSpu', 1)
        }
      })
    },

    // 删除属性值
    handleClose(tag, row) {
      row.spuSaleAttrValueList.splice(row.spuSaleAttrValueList.indexOf(tag), 1)
    },
    // 添加属性名事件函数
    addsaleAttrName(row, index) {
      // row.isShowEdit = false
      this.$set(row, 'isShowEdit', false)
      this.$nextTick(() => {
        this.$refs[index].focus()
      })
    },
    // 失去焦点，添加一个属性值
    addSaleAttrValue(row) {
      const { saleAttrValueName } = this.spu
      if (saleAttrValueName) {
        // 不为空才添加数据
        row.spuSaleAttrValueList.push({
          baseSaleAttrId: row.baseSaleAttrId,
          saleAttrName: row.saleAttrName,
          saleAttrValueName
        })
      }

      row.isShowEdit = true
      this.spu.saleAttrValueName = ''
    },
    // 添加销售属性值
    addSpuAttr() {
      const { saleAttrName } = this.spu

      // 往表格里面添加数据 --> 等于表格每一项的row
      this.spu.spuSaleAttrList.push({
        baseSaleAttrId: this.baseSaleAttrList.find(
          (attr) => attr.name === saleAttrName
        ).id,
        saleAttrName,
        spuSaleAttrValueList: [],
        isShowEdit: true
      })

      this.spu.saleAttrName = ''
    },
    // 删除图片的回调
    handleRemove(file) {
      // 在效果上会删除，但是实际上数据还在，所以要手动删除
      // console.log(file, fileList)
      const url = file.response ? file.response.data : file.url
      this.spu.spuImageList = this.spu.spuImageList.filter(
        (img) => img.imgUrl !== url
      )
    },
    // 预览图片
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url
      this.dialogVisible = true
    },
    // 图片上传前触发的回调
    beforeAvatarUpload(file) {
      // 对上传的图片类型大小进行限制
      const isValidFileType = ['image/jpeg', 'image/jpg', 'image/png'].includes(
        file.type
      )

      const isLtM = file.size / 1024 / 1024 < 1

      if (!isValidFileType) {
        this.$message.error('上传头像图片只能是 JPG 或 PNG 格式!')
      }
      if (!isLtM) {
        this.$message.error('上传头像图片大小不能超过 1MB!')
      }
      return isValidFileType && isLtM
    },
    // 图片上传成功触发的事件
    handleAvatarSuccess(res, file) {
      // 添加一个对象-和服务器要求上传的数据结构一致
      this.spu.spuImageList.push({
        imgName: file.name,
        imgUrl: res.data,
        uid: file.uid
      })
      // 清空表单校验结果
      this.$refs.form.clearValidate(['spuImageList'])
    }
  }
}
</script>

<style lang="sass" scoped>
.table
  margin-top: 20px
.tag-attr-value
  margin-right: 10px
</style>
